#Version 1.1 By eRecruiter team
#3/8/2011
#resume2facts functions as one of the eRecuiter python module for parsing HTMML resume files to CLIPS facts.

import sys,os.path, time, re, datetime
from BeautifulSoup import BeautifulSoup
from BeautifulSoup import BeautifulStoneSoup
from nltk import pos_tag, word_tokenize
from nltk.stem.porter import PorterStemmer
from nltk.stem.wordnet import WordNetLemmatizer

class Person():
    def __init__(self,id=None, name=None, path=None, skillScore=None, leadershipScore=None, educationScore=None, certificateScore=None, totalScore=None):
        self.id=id
        self.name
    
class EmploymentExp():
    
    def __init__(self,id=None,company=None,position=None,duration=None,exp=None):
        self.id=id
        self.company=company
        self.position=position
        self.duration=duration
        self.exp=exp
        self.leadership=self.getLeadership()
        self.workArea=self.getWorkArea()
        
    def getLeadership(self):
        leadership=Leadership(id=self.id,position=self.position,duration=self.duration,company=self.company)
        return leadership
    
    def getWorkArea(self):
        workAreas=[]
        p=self.exp
        v=('VBN','VBD','VB','VBP','VBZ')
        n=('NN','NNS','NNP','NNPS')
        for s in p.split('.'):
            s=s.strip()
            s=s[0].lower()+s[1:]
            if s:
                #print len(s)
                token_pos_pairs=zip(*pos_tag(word_tokenize('I '+s)))
                tmp=[]
                for i in range(0,len(token_pos_pairs[1])):
                    if token_pos_pairs[1][i] in n:
                        tmp.append(token_pos_pairs[0][i].lower())
                    else:
                        if len(tmp)>0:
                            workAreas.append(tmp)
                            tmp=[]
        print workAreas
        for i in range(0,len(workAreas)):
            workAreas[i]=' '.join(workArea[i])
        print workAreas
        exit()
        return workAreas

class Leadership():
    def __init__(self,id=None,position=None,company=None,duration=None):
        self.id=id
        self.position=position
        self.company=company
        self.duration=duration
        level1=['manager','director','president','CEO','CTO']
        level2=['engineer','consultant','programmer','developer','technician','contract','analyst',
                'staff','designer','associate','specialist','assistant','member','architector']
        for title in level1:
            if self.position.lower().find(title)<>-1:
                self.positionScore=100
                break
        try:
            self.positionScore
        except NameError:
            self.positionScore=50
   
class WorkArea():
    def __init__(self,id=None,exp=None):
        self.id=id
        self.name=name
    
class Education():
    def __init__(self,degree=None,major=None,grad_time=None,school=None):
        self.degree=degree
        self.major=major
        self.grad_time=grad_time
        self.school=school

class Resume(object):
    def __init__(self, file=None):
        fr=open(file,'r')
        html=fr.read()
        self.soup=BeautifulSoup(html)
        self.name = self.soup.html.head.title.string
        self.file = file
        
        #exp list of EmploymentExp objects
        self.exp=[]
        self.ParseExp()
        """self.skill=[]
        self.ParseSkill()
        self.edu=[]
        self.ParseEdu()"""

    def ParseExp(self):
        def isNumeric(s):
            try:
                n = float(s)
                return True
            except ValueError:
                return False
                
        body=self.soup.find("body")
        comp_exps=body.findAll('div',attrs={'id' : re.compile("company")})
        count=0
        for comp_exp in comp_exps:
            count+=1
            print count
            company=''
            position=''
            duration=''
            exp=''
            #1. company name
            tmp=comp_exp['title']
            if tmp:
                company=tmp
            #2. position
            tmp=comp_exp.find('div',attrs={'id': re.compile("position")})
            if tmp:
                position=tmp.string.strip()
            #3. duration
            tmp=comp_exp.find('div',attrs={'id': re.compile("time")})
    
            if tmp:
                tmp=tmp.string.strip()
                print tmp
                t={'y1':0,'m1':0,'y2':0,'m2':0}
                m={'jan':1,'feb':2,'mar':3,'apr':4,'may':5,'jun':6,'jul':7,'aug':8,'sep':9,'oct':10,'nov':11,'dec':12}
                if tmp.find(',')<>-1 and tmp.find('-')<>-1:
                    continue
                else:
                    tmp_lst=tmp.split('-')
                    if len(tmp_lst)>2: continue
                    a=tmp_lst[0].lower().strip()
                    b=tmp_lst[1].lower().strip()
                    if isNumeric(a):
                        if len(a)==4:
                            t['y1']=int(a)
                        else:
                            t['y1']=int(a[len(a)-4:])
                            t['m1']=int(a[:len(a)-4])
                    else:
                        if a in ['present','now']:
                            t['y1']=datetime.datetime.now().year
                        else:
                            delimiter=''
                            if a.find('/')<>-1:
                                delimiter='/'
                            elif a.find(',')<>-1:
                                delimiter=','
                            elif a.find(' ')<>-1:
                                delimiter=' '
                            print a.split(delimiter)
                            t['m1'],t['y1']=a.split(delimiter)
                            t['y1']=int(t['y1'].strip())
                            t['m1']=t['m1'].strip()
                            if isNumeric(t['m1']):
                                t['m1']=int(t['m1'])
                            else:
                                t['m1']=m[t['m1'][:3]]
                    
                    if isNumeric(b):
                        if len(b)==4:
                            t['y1']=int(a)
                        else:
                            t['y1']=int(a[len(a)-4:])
                            t['m1']=int(a[:len(a)-4])
                    else:
                        if b in ['present','now']:
                            t['y2']=datetime.datetime.now().year
                        else:
                            delimiter=''
                            if a.find('/')<>-1:
                                delimiter='/'
                            elif a.find(',')<>-1:
                                delimiter=','
                            elif a.find(' ')<>-1:
                                delimiter=' '
                            t['m2'],t['y2']=a.split(delimiter)
                            t['y2']=int(t['y2'].strip())
                            t['m2']=t['m2'].strip()
                            if isNumeric(t['m2']):
                                print t['m2']
                                t['m2']=int(t['m2'])
                            else:
                                print t['m2'][:3]
                                t['m2']=m[t['m2'][:3]]
                print t
            exit()
            #4. exp
            tmp=comp_exp.find('div',attrs={'id': re.compile("experience")})
            if tmp:
                exp=tmp.string.strip()
            #id=None,company=None,position=None,duration=None,exp=None
            new_exp=EmploymentExp('0001',company,position,duration,exp)
            self.exp.append(new_exp)

        
        education=body.find('div',attrs={'id' : re.compile("education")})
        #print body

    def ParseSkill(self):
        """
        Parse skill information form the resume. Skills are uncategorized and can be delimited by line feeds or tabs.
        """
        body=self.soup.find("body")
        skill_div=body.find('div',attrs={'id' : re.compile("skill")})
        set_divs=skill_div.findAll('div',attrs={'id' : re.compile("set")})
        skill_lst=[]
        for set_div in set_divs:
            s='\t'.join(set_div.findAll(text=True)).strip()
            while(s.find(':')<>-1):
                s=s.replace(':','\t')
            while(s.find(',')<>-1):
                s=s.replace(',','\t')
            while(s.find('\n')<>-1):
                s=s.replace('\n','\t')
            while(s.find(';')<>-1):
                s=s.replace(';','\t')
            while(s.find('\t\t')<>-1):
                s=s.replace('\t\t','\t')
            for a in s.split('\t'):
                #convert all skills to lowercase
                b=a.lower().strip()
                if b not in skill_lst:
                    skill_lst.append(b)
        self.skill=skill_lst
        #print skill_lst
    def ParseEdu(self):
        """
        Parse skill information form the resume. Skills are uncategorized and can be delimited by line feeds or tabs.
        """
        body=self.soup.find("body")
        edu_divs=body.find('div',attrs={'id' : re.compile("education")}).findAll('div',attrs={'id' : re.compile("edu")})
        for edu_div in edu_divs:
            degree=edu_div.find('div',attrs={'id' : re.compile("degree")}).string.strip()
            major=edu_div.find('div',attrs={'id' : re.compile("major")}).string.strip()
            grad_time=edu_div.find('div',attrs={'id' : re.compile("deg_time")}).string.strip()
            school=edu_div.find('div',attrs={'id' : re.compile("university")}).string.strip()
            new_edu=Education(degree,major,grad_time,school)
            self.edu.append(new_edu)

    def stem(self,w):
        """
        Get the stem of the word.
        @type w: string
        @param w: the word
        """
        stem=w
        while(1):
            if stem<>PorterStemmer().stem_word(w):
                stem=PorterStemmer().stem_word(w)
            else:
                break
        return stem

    def lemma(self,w):
        """
        Get the lemma of the word.
        @type w: string
        @param w: the word
        """
        lemma=w
        while(1):
            if lemma<>WordNetLemmatizer().lemmatize(w):
                lemma=WordNetLemmatizer().lemmatize(w)
            else:
                break
        return lemma
    
class ResumeParser():
    def __init__(self,file):
        """
        Constructs an ResumeParser.
        @type file: string
        @param file: the name of HTML file to be parsed.
        """
        #print name
        self.candidate=Resume(file)
        exit()
        #self.GenerateClipsCode()
        
        #print self.soup.prettify()
    
    def GenerateClipsCode(self):
        fw=open("clps/"+self.candidate.name+".clp","w")
        s='(deffacts MAIN::'+self.candidate.name+'\n'
        

        print self.candidate.name,"'s information:\n"
        print "-----Working Experiences-----\n"
        count=1
        for exp in self.candidate.exp:
            s+='\t(LeadershipQuality (position %s) (company %s) (duration 1))\n' % (exp.position,exp.company)
            print "company ",count,'\n'
            print 'Name:\t',exp.company
            print 'position:\t',exp.position
            print 'duration:\t',exp.duration
            print 'experience:\t',exp.exp
            print '\n'
            count+=1
        
        print "\n-----Skills-----\n"
        for skill in self.candidate.skill:
            s+='\t(SkillQuality(skill %s))\n' % (skill)
            print skill,'\t'
        count=1
        print "\n-----Education-----\n"
        for edu in self.candidate.edu:
            s+='\t(EducationQuality (degree %s) (major %s) (school %s))\n' % (edu.degree,edu.major,edu.school)
            print "Education ",count,'\n'
            print 'Degree:\t',edu.degree
            print 'Major:\t',edu.major
            print 'Grad time:\t',edu.grad_time
            print 'School:\t',edu.school
            print '\n'
            count+=1
        s+=')'
        fw.write(s)
        
    def clear_screen(self, numlines=100):
        """Clear the console.numlines is an optional argument used only as a fall-back."""
        import os
        if os.name == "posix":
            # Unix/Linux/MacOS/BSD/etc
            os.system('clear')
        elif os.name in ("nt", "dos", "ce"):
            # DOS/Windows
            os.system('CLS')
        else:
            # Fallback for other operating systems.
            print '\n' * numlines
     
if __name__=='__main__':
    reload(sys)
    sys.setdefaultencoding("latin")
    test_files=['data/Alan_Wei.html']
    for file in test_files:
        parser=ResumeParser(file)
    